﻿@model SuperDumpService.ViewModels.ReportViewModel
@using SuperDumpService.Helpers;
@inject IAuthorizationHelper AuthorizationHelper

<script>
	var modalWin = new CreateModalPopUpObject();
	//Uncomment below line to make look buttons as link
	//modalWin.SetButtonStyle("background:none;border:none;textDecoration:underline;cursor:pointer");

	function ShowMessage(msg, lines) {
		modalWin.ShowMessage(msg, 220 + lines * 23, 550, 'User Information');
	}


	function EnrollNow(msg) {
		modalWin.HideModalPopUp();
		modalWin.ShowMessage(msg, 600, 300, 'User Information', null, null);
	}

	function EnrollLater() {
		modalWin.HideModalPopUp();
		modalWin.ShowMessage(msg, 600, 300, 'User Information', null, null);
	}

	function HideModalWindow() {
		modalWin.HideModalPopUp();
	}
</script>



<div class="panel panel-primary">
	<div class="panel-heading">
		<h4 class="panel-title">
			<a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#thread-report">
				Thread report
			</a>
		</h4>
	</div>

	@if (Model.Result.ThreadInformation == null) {
		<div class="alert alert-warning">No thread information available!</div>
	} else {
	<div id="thread-report" class="panel-collapse in">
		<div class="panel-body">
			<button class="btn btn-success" id="openall">Open all</button>
			<button class="btn btn-success" id="closeall">Close all</button>
			<span style="display: inline-block; width:16px">&nbsp;</span>
			@foreach (var tag in Model.ThreadTags.OrderByDescending(t => t.Importance)) {
				<button class="btn btn-primary" onclick="openTabs('@tag.Name')"><span class="tag tag-@tag.Name">@tag.Name</span></button>
			}
			
			<div class="list-group">
				@foreach (var thread in Model.Result.ThreadInformation.Values.OrderByDescending(t => t.Tags.Count == 0 ? 0 : t.Tags.Max(x => x.Importance)).ThenBy(t => t.EngineId)) {
					<a id="@thread.OsId" class="list-group-item thread-heading collapsed" data-toggle="collapse" data-parent="#accordion" href="#thread-@thread.OsId">
						<strong>EngineId: @thread.EngineId</strong> (0x<span>@thread.EngineId.ToString("X")</span>), OsId: @thread.OsId (0x<span>@thread.OsId.ToString("X")</span>)
						@if (!string.IsNullOrEmpty(thread.State)) {
							<span>, ThreadState: @thread.State</span>
						}
						@Html.Partial("Tags", @thread.Tags)
					</a>
					<div id="thread-@thread.OsId" class="thread-div collapse @string.Join(" ", thread.Tags)">
						<!--general information-->
						<table style="width: 100%;">
							<tr>
								<td>
									<dl class="row courier-small compact">
										<dt class="col-sm-3 text-right">Engine thread ID:</dt>
										<dd class="col-sm-9">@thread.EngineId (0x<span>@thread.EngineId.ToString("X")</span>)</dd>

										<dt class="col-sm-3 text-right">OS thread ID:</dt>
										<dd class="col-sm-9">@thread.OsId (0x<span>@thread.OsId.ToString("X")</span>)</dd>

										@if (@thread.IsManagedThread) {
											<dt class="col-sm-3 text-right">Managed thread ID:</dt>
											<dd class="col-sm-9">@thread.ManagedThreadId (0x<span>@thread.ManagedThreadId.ToString("X")</span>)</dd>

											<dt class="col-sm-3 text-right">Thread name:</dt>
											<dd class="col-sm-9">@thread.ThreadName</dd>
										}

										@if (!string.IsNullOrEmpty(thread.State)) {
											<dt class="col-sm-3 text-right">State(s):</dt>
											<dd class="col-sm-9">@thread.State</dd>
										}

										@if (thread.CreationTime > 0) {
											<dt class="col-sm-3 text-right">Creation time:</dt>
											<dd class="col-sm-9">@Utility.ConvertWindowsTimeStamp(thread.CreationTime)</dd>
										}

										@if (thread.KernelTime > 0) {
											<dt class="col-sm-3 text-right">Kernel mode time:</dt>
											<dd class="col-sm-9">@Utility.ConvertWindowsTimeSpan(thread.KernelTime)</dd>
										}

										@if (thread.UserTime > 0) {
											<dt class="col-sm-3 text-right">User mode time:</dt>
											<dd class="col-sm-9">@Utility.ConvertWindowsTimeSpan(thread.UserTime)</dd>
										}

										@if (thread.LastException != null) {
											<dt class="col-sm-3 text-right">Exception Type:</dt>
											<dd class="col-sm-9">@thread.LastException.Type</dd>
											<dt class="col-sm-3 text-right">Exception Message:</dt>
											<dd class="col-sm-9">@thread.LastException.Message</dd>
											<dt class="col-sm-3 text-right">Exception Stack:</dt>
											<dd class="col-sm-9">@Html.Partial("_StacktracePlain", @thread.LastException.StackTrace)</dd>
										}
									</dl>
								</td>
								<td class="thread-toolbox">
									<ul class="flat">
										<li class="text-nowrap"><a href="#@thread.OsId">Permalink</a></li>
										<li class="text-nowrap"><a data-clipboard-target="#thread-@thread.OsId-stacktrace-div" class="copyButton">Copy stack</a> (<a data-clipboard-target="#thread-@thread.OsId-stacktrace-div" class="copyButtonForJira">for JIRA</a>)</li>
										<li class="text-nowrap"><label><input type="checkbox" class="showaddresses" name="@thread.OsId" checked />show addresses</label></li>
										<li class="text-nowrap"><label><input type="checkbox" class="showsourceinfo" name="@thread.OsId" checked />show sourceinfo</label></li>
										<li class="text-nowrap"><label><input type="checkbox" class="showstackptroffset" name="@thread.OsId" />show stackptr offsets</label></li>
										@if (AuthorizationHelper.CheckPolicy(User, LdapCookieAuthenticationExtension.UserPolicy)) {
											<li class="text-nowrap"><label><input type="checkbox" class="showstackvars" name="@thread.OsId" />show stack variables</label></li>
										}
									</ul>
								</td>
							</tr>
						</table>
						<!--stacktraces-->
						<div id="thread-@thread.OsId-stacktrace-div">
							<div class="hidden-stacktrace-hack">
								{noformat}
							</div>
							<table class="table table-stacktrace" id="thread-@thread.OsId-stacktrace">
								<thead>
									<tr>
										@if (Model.DumpType != SuperDumpService.Models.DumpType.LinuxCoreDump) {
											// Frames in core dumps are always native, no need to display
											<th class="nobreak stacktype" style="width: 55px">Type</th>
										}
										<th class="nobreak stackptr" style="width: 79px">StackPtr</th>
										<th class="nobreak stackptroffset">StackPtr.Offset</th>
										<th class="nobreak stackinstructionptr" style="width: 79px">Instruct.Ptr</th>
										<th class="nobreak stackreturnaddr" style="width: 79px">Ret.Addr.</th>
										<th class="nobreak stackmethodname">Module/Method name</th>
									</tr>
								</thead>
								<tbody>
									@{ int frameNr = 0; }
									@foreach (var frame in thread.StackTrace) {
										frameNr++;
										string frameType = string.Empty;
										string rowClass = string.Empty;
										if (frame.Type == SuperDump.Models.StackFrameType.Native) {
											rowClass = "custom-native";
										} else if (frame.Type == SuperDump.Models.StackFrameType.Managed) {
											rowClass = "custom-managed";
										} else if (frame.Type == SuperDump.Models.StackFrameType.Special) {
											rowClass = "custom-special";
										}

										string disassemblyCmd = Model.DumpType == SuperDumpService.Models.DumpType.WindowsDump ?
																										(frame.Type == SuperDump.Models.StackFrameType.Native ? "u " : "!u ") + (frame.InstructionPointer).ToString("x") + "-8" :
																										"disas 0x" + (frame.InstructionPointer).ToString("x");
										<tr id="@frame.StackPointer.ToString("X")" class="@rowClass">
											@if (Model.DumpType != SuperDumpService.Models.DumpType.LinuxCoreDump) {
												<td class="nobreak stacktype">@frame.Type.ToString()</td>
											}
											<td class="nobreak stackptr">@frame.StackPointer.ToString("x" + Model.PointerSize)</td>
											<td class="nobreak stackptroffset">0x<span>@frame.StackPointerOffset.ToString("x")</span> bytes</td>

											<td class="nobreak stackinstructionptr">
												<interactive-link model="@Model" command="@disassemblyCmd">
													@frame.InstructionPointer.ToString("x" + Model.PointerSize)
												</interactive-link>
											</td>
											<td class="nobreak stackreturnaddr">@frame.ReturnOffset.ToString("x" + Model.PointerSize)</td>
											@if (frame.Type == SuperDump.Models.StackFrameType.Special) {
												<td class="nobreak stackmethodname">
													[@(frame.ModuleName)!<b>@(frame.MethodName)</b>+@frame.OffsetInMethod.ToString("x" + Model.PointerSize)]
												</td>
											} else {
												string tagclasses = "";
												if (frame.Tags.Count > 0) {
													tagclasses = "inline-tag " + string.Join(" ", frame.Tags.Select(x => "tag-" + x.Name));
												}
												<td class="nobreak stackmethodname">
													<span class="@tagclasses">@(frame.ModuleName)!<b>@(frame.MethodName)</b>+@(frame.OffsetInMethod.ToString("x"))</span>
													<span class="sourceinfo">
														<dynatrace-source-link repository-url="@Model.RepositoryUrl" source-file="@frame.SourceInfo?.File">@frame.SourceInfo?.File:@frame.SourceInfo?.Line</dynatrace-source-link>
													</span>
													<div class="nobreak stackvariables">
														@if (frame is SuperDumpModels.SDCDCombinedStackFrame) {
															<table>
																@foreach (var entry in (frame as SuperDumpModels.SDCDCombinedStackFrame).ArgsWithLinks) {
																	<tr>
																		<td style="width:120px"><b>@(entry.Key)</b></td>
																		<td>
																			@for (int i = 0; i + 1 < entry.Value.Count(); i += 2) {
																				@(entry.Value.ElementAt(i))
																				<interactive-link Model="@Model" Command="x/32xw @(entry.Value.ElementAt(i + 1))">
																					@(entry.Value.ElementAt(i + 1))
																				</interactive-link>
																			}
																			@(entry.Value.Last())
																		</td>
																	</tr>
																}
																@foreach (var entry in (frame as SuperDumpModels.SDCDCombinedStackFrame).LocalsWithLinks) {
																	<tr>
																		<td style="width:120px"><b>@(entry.Key)</b></td>
																		<td>
																			@for (int i = 0; i + 1 < entry.Value.Count(); i += 2) {
																				@(entry.Value.ElementAt(i))
																				<interactive-link Model="@Model" Command="x/32xw @(entry.Value.ElementAt(i + 1))">
																					@(entry.Value.ElementAt(i + 1))
																				</interactive-link>
																			}
																			@(entry.Value.Last())
																		</td>
																	</tr>
																}
															</table>
														}
													</div>
												</td>
											}

											@if (AuthorizationHelper.CheckPolicy(User, LdapCookieAuthenticationExtension.UserPolicy)) {
												<td class="nobreak stackvariables">
													@if (frame is SuperDumpModels.SDCDCombinedStackFrame) {
														<table>
															@foreach (var entry in (frame as SuperDumpModels.SDCDCombinedStackFrame).ArgsWithLinks) {
																<tr>
																	<td style="width:120px"><b>@(entry.Key)</b></td>
																	<td>
																		@for (int i = 0; i + 1 < entry.Value.Count(); i += 2) {
																			@(entry.Value.ElementAt(i))
																			<interactive-link Model="@Model" Command="x/32xw @(entry.Value.ElementAt(i + 1))">
																				@(entry.Value.ElementAt(i + 1))
																			</interactive-link>
																		}
																		@(entry.Value.Last())
																	</td>
																</tr>
															}
															@foreach (var entry in (frame as SuperDumpModels.SDCDCombinedStackFrame).LocalsWithLinks) {
																<tr>
																	<td style="width:120px"><b>@(entry.Key)</b></td>
																	<td>
																		@for (int i = 0; i + 1 < entry.Value.Count(); i += 2) {
																			@(entry.Value.ElementAt(i))
																			<interactive-link Model="@Model" Command="x/32xw @(entry.Value.ElementAt(i + 1))">
																				@(entry.Value.ElementAt(i + 1))
																			</interactive-link>
																		}
																		@(entry.Value.Last())
																	</td>
																</tr>
															}
														</table>
													}
												</td>
											}
										</tr>
									}
								</tbody>
							</table>
							<div class="hidden-stacktrace-hack">{noformat}</div>
						</div>
					</div>
				}
			</div>
		</div>
	</div>
	}
</div>